from thread_shared_data import ThreadSharedData_StopOnly
import _thread
from machine import PWM, Pin
import time

class LedStyle:
    OFF = 0
    ON = 1
    SLOW_BLINK = 2
    FAST_BLINK = 3
    HEARTBEAT = 4

class LedControl(ThreadSharedData_StopOnly):
    def __init__(self, pin_no: int):
        super().__init__()

        self.pin_no = pin_no

        class LedThreadSharedData(ThreadSharedData_StopOnly):
            def __init__(self):
                super().__init__()
                self.led_style = LedStyle.OFF
                self.brightness = 10

        self.shared_data = LedThreadSharedData()

    def start_led_control(self):
        _thread.start_new_thread(self._led_thread, ())
        self.shared_data.on_thread_start()
        print(f'Led thread (Pin: {self.pin_no}) started.')

    def stop_led_control(self):
        self.shared_data.request_and_wait_thread_exit()

    def set_led_sytle(self, led_style: LedStyle):
        with self.shared_data:
            self.shared_data.led_style = led_style

    """brightness: 0-100"""
    def set_led_brightness(self, brightness: int):
        with self.shared_data:
            self.shared_data.brightness = brightness

    def _on_led_thread_exit(self, pin: PWM):
        print(f'Led thread (Pin: {self.pin_no}) received exit request, exiting...')
        pin.deinit()

    def _led_thread(self):
        pin = PWM(Pin(self.pin_no, Pin.OUT), freq=1000)

        while True:
            with self.shared_data:
                led_style = self.shared_data.led_style
                brightness = self.shared_data.brightness

            brightness_ratio = brightness / 100
            brightness = (int)(65535 * (brightness_ratio ** 2))

            if led_style == LedStyle.OFF:
                pin.duty_u16(0)
                time.sleep(0.1)
            elif led_style == LedStyle.ON:
                pin.duty_u16(brightness)
                time.sleep(0.1)
            elif led_style == LedStyle.SLOW_BLINK:
                pin.duty_u16(brightness)
                time.sleep(0.1)
                pin.duty_u16(0)
                time.sleep(2)
            elif led_style == LedStyle.FAST_BLINK:
                pin.duty_u16(brightness)
                time.sleep(0.1)
                pin.duty_u16(0)
                time.sleep(0.1)
            elif led_style == LedStyle.HEARTBEAT:
                pin.duty_u16(brightness)
                time.sleep(0.1)
                pin.duty_u16(0)
                time.sleep(0.2)
                pin.duty_u16(brightness)
                time.sleep(0.1)
                pin.duty_u16(0)
                time.sleep(1.5)
                
            self.shared_data.check_thread_exit_request(lambda: self._on_led_thread_exit(pin))



if __name__ == '__main__':
    try:
        led_control = LedControl(13)
        led_control.start_led_control()

        # led_control.set_led_sytle(LedStyle.OFF)
        # led_control.set_led_sytle(LedStyle.ON)
        # led_control.set_led_sytle(LedStyle.SLOW_BLINK)
        led_control.set_led_sytle(LedStyle.FAST_BLINK)
        # led_control.set_led_sytle(LedStyle.HEARTBEAT)

        # led_control.set_led_brightness(30)

        # time.sleep(10)
        # led_control.stop_led_control()
    except KeyboardInterrupt:
        led_control.stop_led_control()